前言:最近開始在學新框架了,只是說原生的 javascript 也同時在補足觀念中,最近在複習 this 看當初的筆記,有一種 WTF ,我在寫什麼三小?只能當自己是白紙再看一遍了。 嗚嗚
輔助資源:
猜猜這個 "this" 到底是什麼?
https://youtu.be/8uqUD2F_W74
先說重點:
關鍵:this 決定在於函式如何被呼叫
console.log(this);
在全域執行環境呼叫this,此時它會指向全域物件,也就是window
// Outer Environment
console.log(this);
// function statement
function FunctionStatement() {
console.log(this);
}
FunctionStatement();
// function expression
const FunctionExpression = function() {
console.log(this);
}
FunctionExpression();
這裡的 this 都代表 不管是 function statement 去執行;或是 使用 function expression 執行 只要在全域定義、呼叫創造其執行環境,這時的this會指向全域物件。
var kara = " p助"
function a(){
this.kara = "兔兔"
}
a();
console.log(kara)
console.log 答案是
兔兔 !
我在全域宣告一個變數kara,賦值"p助"。
呼叫函式a時,函式a的執行環境被創造出來,同時函式a的執行環境也創造了它自己的this。
賦值兔兔"給函式a的this.kara,因為函式a自己的this指向全域,這下可好了,在全域的變數kara,其值被蓋過從"p助"變成了"兔兔"。
所以回到這一題,這裡的 this 就是 指全域
var name = '全域';
function callMethod () {
var name = '區域'
console.log(this.name)
}
callMethod();
所以使用this必須要小心,得清楚它指向的物件對象是誰,否則可能會產生一些開發上的bug。
var Qoo = function (){
console.log(this.a);
}
var fpp = function (){
let a =123;
this Qoo();
}
fpp();
答案是 undefined
因為fpp() 透過 this Qoo 取得 Qoo() 這裡的this Qoo指得是 指向 window.Qoo 。 而Qoo()的 this.a 並非fpp()中的123,而是指向 window.a 所以得到undefined 結果。
請看以下問題:
var name = '全域';
function callMethod() {
var name = '區域'
console.log(this.name)
return function () { // << 閉包
var name = '區域的內層變數';
console.log(this.name)
}
}
callMethod()();
1.這裡的callMethod()() 執行的 第五行 function
那如果執行出來的結果會是什麼?
答案是: console.log 出現兩個全域
崩潰了嗎?還沒結束喔? 冷靜三秒,數一下 質數
當沒有特別指名this 的情況下, 預設的this 就是全域物件
var name = '全域';
var object = {
name: 'Object 區域',
callMethod: function () {
var name = '區域';
console.log(this.name);
},
}
object.callMethod();
其中 callMethod 是一個 匿名函式(anonymous function),程式內容很簡單,就是呼叫出 this 而已。最後則是使用 object.callMethod() 的方式來執行該方法。
Ans "Object 區域"
當某個函式是放在某一個物件裡面時,那麼該函式裡面的 this 指稱的就是該物件本身。
這是ES6的東西 可以補充
function 這個詞彙如果使用在物件內,也可以省略 :function,省略後的語意是沒有變化的,並沒有轉而使用箭頭函式。
const newTeam = {
// ...
showPosture: function () {
console.log('我們是 紅黃綠')
}
}
const newTeam = {
// ...
showPosture () {
console.log('我們是 紅黃綠')
}
}
兩個代表一樣意思。
var name = '全域';
var object = {
name: 'Object 區域1',
callMethod: function () {
var name = '區域';
console.log(this.name);
},
abbCallMethod () {
var name = '縮寫函式區域';
console.log(this.name);
}
}
object.callMethod(); //
object.abbCallMethod();
第二個 abbCallMethod 就是物件函式縮寫,
所以跟第一個答案 callMethod() 所得到的答案是一樣的。
var name = '全域';
var object = {
name: 'Object 區域',
arrowCallMethod: () => {
var name = '箭頭函式區域';
console.log(this.name);
}
}
object.arrowCallMethod();
這裡要特別注意,箭頭函式 答案是 全域
因為 箭頭函式 特性有強制綁定 this,所以當我們在寫函式時要注意 。
var elements = document.getElementsByTagName('div');
function style () {
console.log(this);
this.style.border = '1px solid red';
}
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', style, false);
}
這裡 的this 就是我們所執行的 dom 事件 的地方,點擊到的地方
var name = '全域';
var callMethod = function (newName) {
this.name = '權權權';
console.log(this.name);
}
var myName = new callMethod();
console.log(myName.name);
console.log 出來的答案是 權權權
因為 myName 繼承了 callMethod 方法 ,所以 myName.name
答案是 權權權
var name = '全域';
var callMethod = function (newName) {
this.name = newName || '區域';
}
var myName = new callMethod('權權權');
console.log(this.name);
console.log(myName.name);
這裡的 this name 還是指向 全域。
myName.name 就是函式建構式 指的是 權權權。
接下來看陷阱題
var name = '全域';
var callMethod = (newName) => {
this.name = newName || '區域';
}
var myName = new callMethod('卡斯伯');
console.log(this.name);
console.log(myName.name);
這裡不管是哪一個 console.log 都無法執行,因為箭頭函式不能當建構式。
基本上只要看到 bind, apply, call 裡面的this 就是代表綁定的物件
call、apply、bind 三者都是 JavaScript Function 的內建函式,他們與 this 的關係重大,除此之外,call & apply 可以作為呼叫 Function 的另一個手段,而 bind 則會回傳一個經過包裹後的 Function 回來。
function callMethod () {
var name = '區域'
console.log(this.name)
}
callMethod.call({name: '魯魯米'});
這裡的 callMethod 所指就是 魯魯米
bind, call, apply 的差異
可以看這篇文章:
讓你弄懂call、apply、bind的應用和區別
https://juejin.im/post/5a9640335188257a7924d5ef
注意事項
先說結論:setTimeout中所執行函數中的this,永遠指向window!!注意是要延遲執行的函數中的this哦!